/**
 * Copyright @2016-present, Sumscope, Inc.
 * All rights reserved.
 */

const webpack = require('webpack');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackDevMiddleware = require('webpack-dev-middleware');
const { PassThrough } = require('stream');

module.exports = class WebpackMiddleware {
  
  constructor(config) {
    this.compiler = webpack(config);
  }
  
  hotMiddleware(options) {
    const middleware = webpackHotMiddleware(this.compiler, options);
    return async (ctx, next) => {
      let stream = new PassThrough();
      await middleware(ctx.req, {
        write: stream.write.bind(stream),
        writeHead: (state, headers) => {
          ctx.body = stream;
          ctx.state = state;
          ctx.set(headers);
        }
      }, next);
    }
  }
  
  async waitMiddleware(dev, compiler) {
    return new Promise((resolve, reject) => {
      dev.waitUntilValid(() => {
        resolve(true);
      });
      
      compiler.plugin('failed', (error) => {
        reject(error);
      });
    });
  }
  
  devMiddleware(options) {
    const middleware = webpackDevMiddleware(this.compiler, options);
    return async (ctx, next) => {
      await this.waitMiddleware(middleware, this.compiler);
      await middleware(ctx.req, {
        end: (content) => ctx.body = content,
        setHeader: (name, value) => ctx.headers[name] = value
      }, next)
    }
  }
  
};
